import './pickerView.scss'
import {
  memo,
  useState,
  useCallback,
  useEffect,
} from 'react'
import { useDebounceEffect } from '@/library/hooks/use-debounce-effect'
import { withNativeProps } from '../../utils/native-props'
import { useColumnsExtend } from './columnsExtendFix'
import type {
  PickerValue,
  PickerColumnItem,
  PickerColumn,
  PickerValueExtend,
  PickerViewProps,
  WheelProps,
} from './type'
import { Wheel } from './wheel'
import { SpinLoading } from '../SpinLoading'

const classPrefix = 'rt-picker-view'

export type {
  PickerValue,
  PickerColumnItem,
  PickerColumn,
  PickerValueExtend,
  PickerViewProps,
  WheelProps,
}

export const defaultRenderLabel = (item: PickerColumnItem): PickerColumnItem['label'] => item.label

export const PickerView = memo<PickerViewProps>((props) => {
  const {
    columns,
    defaultValue = [],
    initAnimate = false,
    loading,
    loadingContent = (
      <div className={`${classPrefix}-loading-content`}>
        <SpinLoading color="primary" />
      </div>
    ),
    mouseWheel = false,
    renderLabel = defaultRenderLabel,
    onChange,
    value,
  } = props

  const [innerValue, setInnerValue] = useState<PickerValue[]>(
    value === undefined ? defaultValue : value,
  )

  // Sync `value` to `innerValue` reRender
  useEffect(() => {
    if (value === undefined) return
    if (value === innerValue) return
    setInnerValue(value)
  }, [value])

  // async `value` to `innerValue`. 使用场景：受控组件时, 当操作了组件, 调用者没有更新value值，100ms后, reset.
  useEffect(() => {
    if (value === innerValue) return
    const timeout = window.setTimeout(() => {
      if (value !== undefined && value !== innerValue) {
        setInnerValue(value)
      }
    }, 1000)
    return () => {
      window.clearTimeout(timeout)
    }
  }, [value, innerValue])

  const extend = useColumnsExtend(columns, innerValue)

  // trigger `onChange` props
  useDebounceEffect(
    () => {
      if (value === innerValue) return
      onChange?.(innerValue, extend)
    },
    [innerValue],
    {
      wait: 0,
      leading: false,
      trailing: true,
    },
  )

  const handleSelect = useCallback((val: PickerValue, index: number) => {
    setInnerValue((prev) => {
      const next = [...prev]
      next[index] = val
      return next
    })
  }, [])

  return withNativeProps(
    props,
    <div className={classPrefix}>
      {loading ? (
        loadingContent
      ) : (
        <>
          {extend.columns.map((column, index) => (
            <Wheel
              // eslint-disable-next-line react/no-array-index-key
              key={String(index)}
              index={index}
              initAnimate={initAnimate}
              column={column}
              value={innerValue[index]}
              onSelect={handleSelect}
              renderLabel={renderLabel}
              mouseWheel={mouseWheel}
            />
          ))}
          <div className={`${classPrefix}-mask`}>
            <div className={`${classPrefix}-mask-top`} />
            <div className={`${classPrefix}-mask-middle`} />
            <div className={`${classPrefix}-mask-bottom`} />
          </div>
        </>
      )}
    </div>,
  )
})
